﻿using Arction.Wpf.BindableCharting;
using Arction.Wpf.BindableCharting.Series3D;
using Arction.Wpf.BindableCharting.SeriesPolar;
using Arction.Wpf.BindableCharting.SeriesXY;
using Arction.Wpf.BindableCharting.Titles;
using Arction.Wpf.SignalProcessing;
using Prism.Unity;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Threading;
using System.Timers;
using System.Windows.Media;
using WPF_UI_Lightningchart.Helper;
using WPF_UI_Lightningchart.Models;
using Action = System.Action;
using Timer = System.Timers.Timer;

namespace WPF_UI_Lightningchart.ViewModels
{
    public class SensorViewModel : ReactiveObject
    {
        private const int MaxPoints = 100;

        private static readonly Color[] colorArray = new Color[]
        {
            Color.FromArgb(255, 255, 0, 0),    // 红色
            Color.FromArgb(255, 0, 255, 0),    // 绿色
            Color.FromArgb(255, 30, 144, 255), // 深蓝色
            Color.FromArgb(255, 255, 165, 0),  // 橙色
            Color.FromArgb(255, 75, 0, 130),   // 靛蓝色
            Color.FromArgb(255, 238, 130, 238),// 紫罗兰
            Color.FromArgb(255, 255, 69, 0),   // 橙红色
            Color.FromArgb(255, 60, 179, 113), // 海绿色
            Color.FromArgb(255, 255, 105, 180),// 热粉色
            Color.FromArgb(255, 128, 0, 0)     // 栗色
        };

        private Timer _timer;
        private Random _random = new Random();
        private double _speed = 0;

        public string SensorName { get; set; }


        public int _fftDataNumOnce = 50; // 每次FFT数据数量
        public int _intervalFFT = 1000; // FFT间隔
        public int _channelCount = 2;
        public int _samplingFrequency = 1000; // 采样频率
        public int _resolution = 512; // FFT窗口长度
        public int _topFrequency = 120; //最大频率


        [Reactive]public SensorData LatestDataPoint { get; set; }
        public FFTProcessor FFTProcessor { get; set; }
        public AmpPhaProcessor AmpPhaProcessor { get; set; }

        public SensorViewModel(string sensorName)
        {
            SensorName = sensorName;
            AmpPhaProcessor = new AmpPhaProcessor(SensorName);
            ConfigureTimer();

            FFTProcessor = new FFTProcessor(_fftDataNumOnce, _samplingFrequency, _intervalFFT, _resolution, _channelCount);
            Thread dataAddingThread = new Thread(() => AddComplexWaveDataContinuously(FFTProcessor,40,30));
            dataAddingThread.Start();
        }
        #region FFT
        private void AddComplexWaveDataContinuously(FFTProcessor fftProcessor, float baseFrequency, float amplitude)
        {
            Random random = new Random();
            int sampleRate = 1000;
            int dataLength = 50; 
            float time = 0;
            float deltaT = 1.0f / sampleRate;
            double speed = 0;
            while (true)
            {
                float[] leftValues = new float[dataLength];
                float[] rightValues = new float[dataLength];

                for (int i = 0; i < dataLength; i++)
                {
                    float baseSignal = amplitude * (float)Math.Sin(2 * Math.PI * baseFrequency * time);
                    float highFrequencySignal = (amplitude / 2) * (float)Math.Sin(2 * Math.PI * (baseFrequency * 2) * time);
                    float lowFrequencySignal = (amplitude / 3) * (float)Math.Cos(2 * Math.PI * (baseFrequency / 2) * time);

                    leftValues[i] = baseSignal + highFrequencySignal + lowFrequencySignal;
                    rightValues[i] = baseSignal + highFrequencySignal + lowFrequencySignal;
                    time += deltaT;
                }

                fftProcessor.AddData(leftValues, rightValues, speed);
                speed += 0.1;
                int sleepTime = (int)(dataLength / (float)sampleRate * 1000);
                Thread.Sleep(sleepTime);
            }
        }

        private void saveFFT(double[][][] xValues, double[][][] yValues)
        {

        }
        #endregion FFT

        private void ConfigureTimer()
        {
            int sensorIndex = GetSensorIndex(SensorName);
            _timer = new Timer(10 + 5 * sensorIndex);
            _timer.Elapsed += (s, e) => UpdateData();
            _timer.Start();
        }

        private int GetSensorIndex(string sensorName)
        {
            return int.TryParse(new string(sensorName.Where(char.IsDigit).ToArray()), out int index) ? index : 1;
        }

        public void StopData() 
        {
            _timer.Stop();
        }

        private void UpdateData()
        {
            var newData = GenerateSensorData();
            AmpPhaProcessor.UpdateXYSeries(newData.Speed, newData.Amplitude, newData.Phase);
            AmpPhaProcessor.UpdatePolarSeries(newData.Amplitude, newData.Phase);
            UpdateLatestDataPoint(newData);
        }

        private SensorData GenerateSensorData()
        {
            int sensorIndex = GetSensorIndex(SensorName);
            _speed += 0.1;
            return new SensorData
            {
                SensorName = SensorName,
                Timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                Value = SensorName.Contains("传感器001") ? _random.Next(20, 30) : _random.Next(30, 100),
                Unit = SensorName.Contains("传感器001") ? "cm/ms" : "m/s",
                Amplitude = _random.Next(0, 50) + sensorIndex * 10,
                Phase = _random.Next(0, 360),
                Speed = _speed
            };
        }

        private void UpdateLatestDataPoint(SensorData newData)
        {
            PrismApplication.Current.Dispatcher.BeginInvoke((Action)(() => LatestDataPoint = newData));
        }
    }
}
